package com.tyj.movie.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tyj.movie.constant.AjaxConstant;
import com.tyj.movie.entity.*;
import com.tyj.movie.mapper.*;
import com.tyj.movie.service.MovieService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tyj.movie.service.MovieTypeService;
import com.tyj.movie.util.R;
import com.tyj.movie.util.SecurityUtil;
import com.tyj.movie.vo.CinemasMovieVo;
import com.tyj.movie.vo.MainPageMovieVo;
import com.tyj.movie.vo.MovieCommentVo;
import com.tyj.movie.vo.MovieDetailVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author tyj
 * @since 2021-06-28
 */
@Service
@Slf4j
public class MovieServiceImpl extends ServiceImpl<MovieMapper, Movie> implements MovieService {

    @Autowired
    MovieMapper movieMapper;

    @Autowired
    ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    MovieTypeMapper movieTypeMapper;

    @Autowired
    MovieAreaMapper movieAreaMapper;

    @Autowired
    MoviePictureSetMapper moviePictureSetMapper;

    @Autowired
    MovieActorMapper actorMapper;

    @Autowired
    WatchNumberUserRelationMapper watchNumberUserRelationMapper;

    @Autowired
    MovieCommentMapper movieCommentMapper;

    @Autowired
    GiveLikeRelationMapper giveLikeRelationMapper;
    /**
     * 查询热映电影
     *
     * @return
     */
    @Cacheable(value = "movie", key = "#root.method.name", sync = true)
    public HashMap<String, Object> queryHotShowMovie() {
        log.debug("从数据库中查询热映电影");
        HashMap<String, Object> hashMap = new HashMap<>();
        List<Movie> movies = movieMapper.queryHotShowMovie();
        Integer integer = movieMapper.queryHotShowMovieNum();
        hashMap.put("data", movies);
        hashMap.put("total", integer);
        return hashMap;
    }

    /**
     * 查询即将上映电影
     *
     * @return
     */
    @Cacheable(value = "movie", key = "#root.method.name", sync = true)
    public HashMap<String, Object> queryComingMovies() {
        log.debug("从数据库中查询即将上映电影");
        HashMap<String, Object> hashMap = new HashMap<>();
        List<Movie> movies = movieMapper.queryComingMovies();
        Integer integer = movieMapper.queryComingMoviesNum();
        hashMap.put("data", movies);
        hashMap.put("total", integer);
        return hashMap;
    }

    /**
     * 查询热播电影
     *
     * @return
     */
    @Cacheable(value = "movie", key = "#root.method.name", sync = true)
    public List<Movie> queryHotMovies() {
        log.debug("从数据库中查询热播电影");
        List<Movie> movies = movieMapper.queryHotMovies();
        return movies;
    }


    /**
     * 更新热映电影
     *
     * @return
     */
    @CachePut(value = "movie", key = "'queryHotShowMovie'")
    public HashMap<String, Object> updateHotShowMovie() {
        HashMap<String, Object> hashMap = new HashMap<>();
        List<Movie> movies = movieMapper.queryHotShowMovie();
        Integer integer = movieMapper.queryHotShowMovieNum();
        hashMap.put("data", movies);
        hashMap.put("total", integer);
        return hashMap;
    }

    /**
     * 更新即将上映电影
     *
     * @return
     */
    @CachePut(value = "movie", key = "'queryComingMovies'")
    public HashMap<String, Object> updateComingMovies() {
        HashMap<String, Object> hashMap = new HashMap<>();
        List<Movie> movies = movieMapper.queryComingMovies();
        Integer integer = movieMapper.queryComingMoviesNum();
        hashMap.put("data", movies);
        hashMap.put("total", integer);
        return hashMap;
    }

    /**
     * 更新热播电影
     *
     * @return
     */
    @CachePut(value = "movie", key = "'queryHotMovies'")
    public List<Movie> updateHotMovies() {
        List<Movie> movies = movieMapper.queryHotMovies();
        return movies;
    }

    @Override
    public MovieDetailVo queryMovieDetail(Long id) throws ExecutionException, InterruptedException {
        //封装数据
        MovieDetailVo movieDetailVo = new MovieDetailVo();
        Users user = SecurityUtil.getSessionUser();

        //1.查询电影
        CompletableFuture<Void> movieCompletableFuture = CompletableFuture.runAsync(() -> {
            Movie movie = movieMapper.selectOne(new QueryWrapper<Movie>().eq("id", id).eq("state", 0));
            BeanUtils.copyProperties(movie, movieDetailVo);
        }, threadPoolExecutor);

        //2.查询类型
        CompletableFuture<Void> completableFuture = movieCompletableFuture.runAsync(() -> {
            List<String> movieTypes = movieTypeMapper.queryMovieTypesByMovieId(id);
            movieDetailVo.setMovieTypes(movieTypes);
        }, threadPoolExecutor);

        //3.查询区域
        CompletableFuture<Void> completableFuture1 = movieCompletableFuture.runAsync(() -> {
            List<String> movieAreas = movieAreaMapper.queryMovieAreasByMovieId(id);
            movieDetailVo.setMovieAreas(movieAreas);
        }, threadPoolExecutor);

        //4.查询图集
        CompletableFuture<Void> completableFuture2 = movieCompletableFuture.runAsync(() -> {
            List<MoviePictureSet> moviePictureSets = moviePictureSetMapper.selectList(new QueryWrapper<MoviePictureSet>().eq("movie_id", id));
            movieDetailVo.setMoviePictureSets(moviePictureSets);
        }, threadPoolExecutor);

        //5.查询演员
        CompletableFuture<Void> completableFuture3 = movieCompletableFuture.runAsync(() -> {
            List<MovieActor> movieActors = actorMapper.queryActorByMovieId(id);
            movieDetailVo.setMovieActors(movieActors);
        }, threadPoolExecutor);

        //6.判断是否点击过
        CompletableFuture<Void> completableFuture4 = movieCompletableFuture.runAsync(() -> {
            if (user != null) {
                QueryWrapper<WatchNumberUserRelation> eq = new QueryWrapper<WatchNumberUserRelation>().eq("user_id", user.getId()).eq("movie_id", id).eq("state", 0);
                WatchNumberUserRelation watchNumberUserRelation = watchNumberUserRelationMapper.selectOne(eq);
                if (watchNumberUserRelation == null) {
                    movieDetailVo.setWhetherWatch(1);
                } else {
                    movieDetailVo.setWhetherWatch(0);
                }
            }
        }, threadPoolExecutor);

        //7.查询评论
        CompletableFuture<Void> completableFuture5 = movieCompletableFuture.runAsync(() -> {
            //查询所有评论
           List<MovieCommentVo> list = movieCommentMapper.selectListMovieCommentVo(id);
            //查询评分人数
            Integer movieNumber = movieCommentMapper.queryCommentMumberByMovieId(id);

            MovieCommentVo myMovieComment=null;
           //找到我评论的
            if (user!=null){
                for (MovieCommentVo movieCommentVo : list) {
                    if (movieCommentVo.getUserId().equals(user.getId())){
                        myMovieComment=movieCommentVo;
                        break;
                    }
                }
                //查询我点过赞的
                List<GiveLikeRelation> giveLikeRelations = giveLikeRelationMapper.selectList(new QueryWrapper<GiveLikeRelation>().eq("user_id", user.getId()).eq("movie_id", id));
                for (GiveLikeRelation giveLikeRelation : giveLikeRelations) {
                    for (MovieCommentVo movieCommentVo : list) {
                        if (giveLikeRelation.getMovieCommentId().equals(movieCommentVo.getId())){
                            movieCommentVo.setWhetherGiveLike(true);
                        }
                    }
                }
            }

            movieDetailVo.setCommentNumber(movieNumber);
            movieDetailVo.setMovieComments(list);
            movieDetailVo.setMyMovieComments(myMovieComment);
        }, threadPoolExecutor);


        CompletableFuture.allOf(completableFuture, completableFuture1, completableFuture2, completableFuture3,completableFuture4,completableFuture5).get();
        return movieDetailVo;
    }

    @Override
    @Transactional
    public R wantSee(Long id) {
        //得到用户id
        Long userId = SecurityUtil.getSessionUser().getId();
        //判断用户是否想看过
        WatchNumberUserRelation numberUserRelation = watchNumberUserRelationMapper.selectOne(new QueryWrapper<WatchNumberUserRelation>().eq("user_id", userId).eq("movie_id",id));
        if (numberUserRelation == null || numberUserRelation.getState().equals(1)) {
            //未点击过
            //增加电影的想看数量
            movieMapper.updateWatchNumberAddByMovieId(id);
            //判断数据库是否有该数据
            if (numberUserRelation == null) {
                //增加关系表
                WatchNumberUserRelation watchNumberUserRelation = new WatchNumberUserRelation();
                watchNumberUserRelation.setMovieId(id);
                watchNumberUserRelation.setUserId(userId);
                watchNumberUserRelation.setState(0);
                watchNumberUserRelationMapper.insert(watchNumberUserRelation);
            }else {
                //修改关系表状态
                WatchNumberUserRelation watchNumberUserRelation = new WatchNumberUserRelation();
                watchNumberUserRelation.setMovieId(id);
                watchNumberUserRelation.setUserId(userId);
                watchNumberUserRelation.setState(0);
                watchNumberUserRelation.setId(numberUserRelation.getId());
                watchNumberUserRelationMapper.updateById(watchNumberUserRelation);
            }

            return R.ok(AjaxConstant.AJAX_USER_WATCH_YES.getCode(), AjaxConstant.AJAX_USER_WATCH_YES.getMsg());

        } else {
            //点击过
            //减少电影的想看数量
            movieMapper.updateWatchNumberReduceByMovieId(id);
            //修改关系表
            WatchNumberUserRelation watchNumberUserRelation = new WatchNumberUserRelation();
            watchNumberUserRelation.setMovieId(id);
            watchNumberUserRelation.setUserId(userId);
            watchNumberUserRelation.setState(1);
            watchNumberUserRelation.setId(numberUserRelation.getId());
            watchNumberUserRelationMapper.updateById(watchNumberUserRelation);

            //判断评论是否评论过
            MovieComment movieComment = movieCommentMapper.selectOne(new QueryWrapper<MovieComment>().eq("user_id", userId).eq("movie_id", id));
            if (movieComment!=null){
                //评论过删除评论
                movieCommentMapper.delete(new UpdateWrapper<MovieComment>().eq("user_id", userId).eq("movie_id", id));
            }
            return R.ok(AjaxConstant.AJAX_USER_WATCH_NO.getCode(), AjaxConstant.AJAX_USER_WATCH_NO.getMsg());
        }

    }

    /**
     * 更新电影评论级别
     */
    @Override
    public void statCommentLevel() {
        //查询电影id与平均评论分
       List<Movie> movieList = movieMapper.queryCommentLevelAndMovieId();
       //批量修改电影评分
        movieMapper.batchUpdateMovieGrade(movieList);
//        for (Movie movie : movieList) {
//            this.baseMapper.update(movie,new UpdateWrapper<Movie>().set("grade",movie.getGrade()).eq("id",movie.getId()));
//        }
    }

    /**
     * 电影页
     * @param movieShow 电影显示状态 1正在热映 2即将上映 3经典影片
     * @param movieType 电影类型
     * @param movieArea 电影区域
     * @param movieSort 电影排序 1热门排序 2时间排序 3评论排序
     * @param pageNum 页数
     * @return
     */
    @Override
    public IPage<Movie> conditionQueryMovie(String movieShow, String movieType, String movieArea, String movieSort,Long pageNum) {
        Page page=new Page(pageNum,6);
        IPage<Movie> movieIPage= movieMapper.conditionQueryMovie(page,movieShow,movieType,movieArea,movieSort);
        return movieIPage;
    }

    @Override
    public CinemasMovieVo queryCinemasMovieVo(Long movieId) {
        CinemasMovieVo cinemasMovieVo =  movieMapper.queryCinemasMovieVo(movieId);
        return cinemasMovieVo;
    }


}
